// Copyright Epic Games, Inc. All Rights Reserved. // 版权声明

#include "LyraAbilitySet.h" // 包含头文件

#include "AbilitySystem/Abilities/LyraGameplayAbility.h" // 包含Lyra游戏能力头文件
#include "LyraAbilitySystemComponent.h" // 包含Lyra能力系统组件头文件
#include "LyraLogChannels.h" // 包含Lyra日志频道头文件

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraAbilitySet) // 包含内联生成的C++代码

/**
 * 添加能力规格句柄到已授予句柄集合中
 * @param Handle 要添加的能力规格句柄
 */
void FLyraAbilitySet_GrantedHandles::AddAbilitySpecHandle(const FGameplayAbilitySpecHandle& Handle)
{
	if (Handle.IsValid()) // 检查句柄是否有效
	{
		AbilitySpecHandles.Add(Handle); // 将有效句柄添加到能力规格句柄数组中
	}
}

/**
 * 添加游戏效果句柄到已授予句柄集合中
 * @param Handle 要添加的游戏效果句柄
 */
void FLyraAbilitySet_GrantedHandles::AddGameplayEffectHandle(const FActiveGameplayEffectHandle& Handle)
{
	if (Handle.IsValid()) // 检查句柄是否有效
	{
		GameplayEffectHandles.Add(Handle); // 将有效句柄添加到游戏效果句柄数组中
	}
}

/**
 * 添加属性集到已授予句柄集合中
 * @param Set 要添加的属性集指针
 */
void FLyraAbilitySet_GrantedHandles::AddAttributeSet(UAttributeSet* Set)
{
	GrantedAttributeSets.Add(Set); // 将属性集指针添加到已授予属性集数组中
}

/**
 * 从能力系统组件中移除所有已授予的内容
 * @param LyraASC 目标Lyra能力系统组件
 */
void FLyraAbilitySet_GrantedHandles::TakeFromAbilitySystem(ULyraAbilitySystemComponent* LyraASC)
{
	check(LyraASC); // 断言检查LyraASC指针有效性

	if (!LyraASC->IsOwnerActorAuthoritative()) // 检查是否为权威端
	{
		// Must be authoritative to give or take ability sets. // 必须是权威端才能给予或移除能力集
		return; // 非权威端直接返回
	}

	for (const FGameplayAbilitySpecHandle& Handle : AbilitySpecHandles) // 遍历所有能力规格句柄
	{
		if (Handle.IsValid()) // 检查句柄是否有效
		{
			LyraASC->ClearAbility(Handle); // 从能力系统组件中清除指定能力
		}
	}

	for (const FActiveGameplayEffectHandle& Handle : GameplayEffectHandles) // 遍历所有游戏效果句柄
	{
		if (Handle.IsValid()) // 检查句柄是否有效
		{
			LyraASC->RemoveActiveGameplayEffect(Handle); // 从能力系统组件中移除活跃游戏效果
		}
	}

	for (UAttributeSet* Set : GrantedAttributeSets) // 遍历所有已授予属性集
	{
		LyraASC->RemoveSpawnedAttribute(Set); // 从能力系统组件中移除生成的属性集
	}

	AbilitySpecHandles.Reset(); // 重置能力规格句柄数组
	GameplayEffectHandles.Reset(); // 重置游戏效果句柄数组
	GrantedAttributeSets.Reset(); // 重置已授予属性集数组
}

/**
 * 构造函数
 * @param ObjectInitializer 对象初始化器
 */
ULyraAbilitySet::ULyraAbilitySet(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer) // 调用父类构造函数
{
}

/**
 * 将能力集授予指定的能力系统组件
 * @param LyraASC 目标Lyra能力系统组件
 * @param OutGrantedHandles 输出参数，存储所有已授予内容的句柄
 * @param SourceObject 源对象，用于能力规格
 */
void ULyraAbilitySet::GiveToAbilitySystem(ULyraAbilitySystemComponent* LyraASC, FLyraAbilitySet_GrantedHandles* OutGrantedHandles, UObject* SourceObject) const
{
	check(LyraASC); // 断言检查LyraASC指针有效性

	if (!LyraASC->IsOwnerActorAuthoritative()) // 检查是否为权威端
	{
		// Must be authoritative to give or take ability sets. // 必须是权威端才能给予或移除能力集
		return; // 非权威端直接返回
	}
	
	// Grant the attribute sets. // 授予属性集
	for (int32 SetIndex = 0; SetIndex < GrantedAttributes.Num(); ++SetIndex) // 遍历所有要授予的属性集
	{
		const FLyraAbilitySet_AttributeSet& SetToGrant = GrantedAttributes[SetIndex]; // 获取当前要授予的属性集配置

		if (!IsValid(SetToGrant.AttributeSet)) // 检查属性集类是否有效
		{
			UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedAttributes[%d] on ability set [%s] is not valid"), SetIndex, *GetNameSafe(this)); // 记录错误日志
			continue; // 跳过无效的属性集
		}

		UAttributeSet* NewSet = NewObject<UAttributeSet>(LyraASC->GetOwner(), SetToGrant.AttributeSet); // 创建新的属性集对象
		LyraASC->AddAttributeSetSubobject(NewSet); // 将属性集添加到能力系统组件中

		if (OutGrantedHandles) // 检查输出句柄参数是否有效
		{
			OutGrantedHandles->AddAttributeSet(NewSet); // 将新属性集添加到输出句柄中
		}
	}

	// Grant the gameplay abilities. // 授予游戏能力
	for (int32 AbilityIndex = 0; AbilityIndex < GrantedGameplayAbilities.Num(); ++AbilityIndex) // 遍历所有要授予的游戏能力
	{
		const FLyraAbilitySet_GameplayAbility& AbilityToGrant = GrantedGameplayAbilities[AbilityIndex]; // 获取当前要授予的游戏能力配置

		if (!IsValid(AbilityToGrant.Ability)) // 检查能力类是否有效
		{
			UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedGameplayAbilities[%d] on ability set [%s] is not valid."), AbilityIndex, *GetNameSafe(this)); // 记录错误日志
			continue; // 跳过无效的能力
		}

		ULyraGameplayAbility* AbilityCDO = AbilityToGrant.Ability->GetDefaultObject<ULyraGameplayAbility>(); // 获取能力的默认对象

		FGameplayAbilitySpec AbilitySpec(AbilityCDO, AbilityToGrant.AbilityLevel); // 创建能力规格
		AbilitySpec.SourceObject = SourceObject; // 设置能力源对象
		AbilitySpec.GetDynamicSpecSourceTags().AddTag(AbilityToGrant.InputTag); // 添加输入标签到能力规格的动态源标签中

		const FGameplayAbilitySpecHandle AbilitySpecHandle = LyraASC->GiveAbility(AbilitySpec); // 将能力授予能力系统组件并获取句柄

		if (OutGrantedHandles) // 检查输出句柄参数是否有效
		{
			OutGrantedHandles->AddAbilitySpecHandle(AbilitySpecHandle); // 将能力规格句柄添加到输出句柄中
		}
	}

	// Grant the gameplay effects. // 授予游戏效果
	for (int32 EffectIndex = 0; EffectIndex < GrantedGameplayEffects.Num(); ++EffectIndex) // 遍历所有要授予的游戏效果
	{
		const FLyraAbilitySet_GameplayEffect& EffectToGrant = GrantedGameplayEffects[EffectIndex]; // 获取当前要授予的游戏效果配置

		if (!IsValid(EffectToGrant.GameplayEffect)) // 检查游戏效果类是否有效
		{
			UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedGameplayEffects[%d] on ability set [%s] is not valid"), EffectIndex, *GetNameSafe(this)); // 记录错误日志
			continue; // 跳过无效的游戏效果
		}

		const UGameplayEffect* GameplayEffect = EffectToGrant.GameplayEffect->GetDefaultObject<UGameplayEffect>(); // 获取游戏效果的默认对象
		const FActiveGameplayEffectHandle GameplayEffectHandle = LyraASC->ApplyGameplayEffectToSelf(GameplayEffect, EffectToGrant.EffectLevel, LyraASC->MakeEffectContext()); // 将游戏效果应用到自身并获取句柄

		if (OutGrantedHandles) // 检查输出句柄参数是否有效
		{
			OutGrantedHandles->AddGameplayEffectHandle(GameplayEffectHandle); // 将游戏效果句柄添加到输出句柄中
		}
	}
}